﻿using System;

namespace 面向对象_委托2
{
    class Program
    {
        static void Main(string[] args)
        {
            var boy = new Student();
            var girl = new Girl();
            var tech = new Teacher();
            var bro = new Bro();

            // 委托如果连续使用 = 赋值，会发生覆盖，只能执行最后赋值的那个方法
            // 在本情境中出现了委托的分发的需求 （委托的多播）
            // 实现委托的多播：+= 添加（叠加的过程）；-= 移除
            // 多播委托事件监听的顺序决定了执行和输出的顺序
            //当使用 自己实现的属性的话，需要使用等号，一定不能使用 += ，否则会重复添加
            bro.OnFoodReached += boy.Do;
            bro.OnFoodReached += girl.Do;
            bro.OnFoodReached += tech.Do;

            bro.ReportPositon(50);
            Console.WriteLine("-------分割--------");
            bro.ReportPositon(15);

        }
    }
        // 委托一般用于观察者模式（监听模式）
        // 理解观察者模式： 观察者、被观察者，如果被观察者有出现 观察者关心的动作 ，观察者也会采取措施

        // 等外卖:
        // 被观察者：外卖小哥
        // 观察者： 你
        // 关心的动作：外卖小哥离我 20 米
        //  观察者的行为：准备好开饭了

        //  第二个观察者：女朋友
        //  观察者的行为：云共餐

        //   第三个观察者：老师
        //   观察者的行为：看你还在不在专心的听讲

        public delegate void 外卖到了();

        class Person
        {
            public virtual void Do()
            {
            }
        }

        /// <summary>
        ///  学生
        /// </summary>
        class Student : Person
        {
            public override void Do()
            {
                Console.WriteLine($"xxx：餐要到了，准备接餐");
            }
        }

        /// <summary>
        /// 女孩
        /// </summary>
        class Girl : Person
        {
            public override void Do()
            {
                Console.WriteLine("女朋友：我要和 xxx 云共餐");
            }
        }
        /// <summary>
        /// 老师
        /// </summary>
        class Teacher : Person
        {
            public override void Do()
            {
                Console.WriteLine("老师：点餐的 xxx 专心听讲");
            }
        }

    /// <summary>
    /// 小哥
    /// </summary>
    class Bro // 兄弟 brother 的缩写
    {
        /// <summary>
        /// 事件：当食物到达的时候委托
        /// </summary>
        // On :当 xxxx 的时候
        // Food ：食物
        // Reached :到达
        public 外卖到了 OnFoodReached;

        /// <summary>
        /// 报告位置
        /// </summary>
        /// <param name="distance">小哥上传的距离</param>
        public void ReportPositon(int distance)
        {
            if (distance <= 20)
            {
                Console.WriteLine($"小哥：距离客户 {distance} 米,请准备接餐");
                OnFoodReached?.Invoke();
            }
            else
            {
                Console.WriteLine($"小哥：距离客户 {distance} 米,请耐心等待");
            }
        }
    }
}
